/**************************************************************************************
* Entity.java
* 
*************************************************************************************/
package creid.mythos.engine;

import java.io.Serializable;
import java.util.HashMap;

public class Entity implements Serializable, Comparable<Entity>
{
	//Constants/////////////////////////////////////////////////////////////////////////

	private static final long serialVersionUID = 6987108605294325588L;

	public static final int UNIQUE = -1;
	
	public static final boolean DEFINITE = true;
	public static final boolean INDEFINITE = false;
	
	public static final int SPRITE_SIZE = 2;
	
	//Elements
	public static final int PHYSICAL = 0;
	public static final int MENTAL = 1;
	public static final int ELECTRICAL = 2;
	public static final int FIRE = 3;
	public static final int LIGHT = 4;
	public static final int SHADOW = 5;
	public static final int ACID = 6;
	public static final int HEAL = 7;
	public static final int NUM_ELEMENTS = 8;

	//Status effects are defended by defense type 1
	public static final int WEAKNESS = 7;
	
	//Procedural generation constants
	public static final int NEVER_GEN = 0;
	public static final int GEN_RARE = 1;
	public static final int GEN_RARE_ENTRIES = 1;
	public static final int GEN_UNCOMMON = 2;
	public static final int GEN_UNCOMMON_ENTRIES = 4;
	public static final int GEN_COMMON = 3;
	public static final int GEN_COMMON_ENTRIES = 10;
	
	public static final int VERY_COMMON = 100;
	public static final int COMMON = 80;
	public static final int UNCOMMON = 50;
	public static final int VERY_UNCOMMON = 30;
	public static final int RARE = 10;
	public static final int VERY_RARE = 5;
	public static final int EXTREMELY_RARE = 1;
	
	//Attributes////////////////////////////////////////////////////////////////////////
	
	private int id;
	
	//Singular and plural names
	private String sname;
	private String pname;
	
	private String[] details;
	
	boolean useAn;
	
	private int amount; //count
	
	//private Sprite sprite;
	private char[] sprite;
	
	//Derived stats
	protected int level;
	
	protected int rarity;
	
	//Miscellaneous properties
	private HashMap<String, Integer> properties;

	//Constructors//////////////////////////////////////////////////////////////////////
	
	public int getRarity()
	{
		return rarity;
	}

	public void setRarity(int rarity)
	{
		this.rarity = rarity;
	}

	public Entity(int id, String singular, String plural, char[] sprite, int level, int rarity)
	{
		this.id = id;
		this.level = level;
		sname = singular;
		pname = plural;
		
		if (pname == null)
			pname = sname + "s"; //crude guess
		
		this.sprite = sprite;
		amount = 1;
		useAn = false;
		
		char a = singular.toLowerCase().charAt(0);
		if (a == 'a' || a == 'e' || a == 'i' || a == 'o' || a == 'u')
			useAn = true;
		
		this.rarity = rarity;
		
		properties = new HashMap<String, Integer>();
	}
	
	public Entity(Entity other)
	{
		id = other.id;
		sname = other.sname;
		pname = other.pname;
		sprite = other.sprite;
		amount = other.amount;
		useAn = other.useAn;
		level = other.level;
		rarity = other.rarity;
		properties = new HashMap<String, Integer>();
		
		//Copy the other's properties
		for (String key: other.properties.keySet())
		{
			properties.put(key, new Integer(other.properties.get(key)));
		}
	}
	
	//Methods///////////////////////////////////////////////////////////////////////////
	
	public boolean hasProperty(String name)
	{
		if (getProperty(name) == 0)
			return false;
		else
			return true;
	}
	
	public int getProperty(String name)
	{
		if (properties.get(name) == null)
		{
			//Mythos.logger.errorLog("Entity.getPropery() called with unknown property '" + name +"'");
			return 0;
		}
		else
		{
			return properties.get(name);
		}
	}
	
	public int setProperty(String name, int value)
	{
		int val = FileHandler.NULL_INT;
		
		if (properties.get(name) != null)
		{
			val = properties.get(name);
		}

		properties.put(name, value);
		
		return val;
	}

	public int getLevel()
	{
		return level;
	}

	public void setLevel(int level)
	{
		this.level = level;
	}
	
	public void setSingularName(String name)
	{
		sname = name;
		char a = sname.toLowerCase().charAt(0);
		if (a == 'a' || a == 'e' || a == 'i' || a == 'o' || a == 'u')
			useAn = true;
	}
	
	public void setPluralName(String name)
	{
		pname = name;
	}
	
	public char[] getSprite()
	{
		return sprite;
	}
	
	public void setSprite(char[] sprite)
	{
		this.sprite = sprite;
	}
	
	public int getAmount()
	{
		return amount;
	}
	
	public void setDetails(String[] details)
	{
		this.details = details;
	}

	public void setAmount(int amount)
	{
		this.amount = amount;
	}

	protected String getSingularName()
	{
		return sname;
	}
	
	protected String getPluralName()
	{
		return pname;
	}
	
	public String getName(boolean article)
	{
		String output = "";
		//Unique entities are proper nouns, "first names" if you will, and don't use articles
		if (amount == UNIQUE)
		{
			output = sname;
		}
		//Get the article figured out
		else
		{
			if (article)
				output = "the ";
			else if (amount == 1) //Determine whether to use 
			{
				if (useAn)
					output = "an ";
				else
					output = "a ";
			}
			
			if (amount == 1)
				output += sname;
			else
				output += amount + " " + pname;
		}
		
		return output;
	}
	
	public String[] getDetails()
	{
		return details;
	}
	
	@Override
	public String toString()
	{
		return getName(INDEFINITE);
	}

	public int getId()
	{
		return id;
	}

	public void setId(int id)
	{
		this.id = id;
	}

	@Override
	public int compareTo(Entity other)
	{
		if (id != other.id)
			return id - other.id;
		else return getSingularName().compareTo(other.getSingularName()); 
	}
}
